﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace Baggr.SqlServer
{
    public class ComputeLSAProcedure
    {
        [SqlProcedure]
        public static void ComputeLsaInternal(SqlInt32 dataSetId)
        {
            using (var connection = new SqlConnection(@"context connection=true"))
            {
                connection.Open();
                var feedNomberById = new Dictionary<Guid, int>();
                var feedIdByNomber = new Dictionary<int, Guid>();
                var wordNomberById = new Dictionary<int, int>();
                var wordIdByNomber = new Dictionary<int, int>();
                double[,] source;
                using (var getDataCommand = new SqlCommand("GetDataForLSA", connection))
                {
                    getDataCommand.CommandType = CommandType.StoredProcedure;
                    getDataCommand.Parameters.AddWithValue("@DataSetId", dataSetId);
                    using (var dataReader = getDataCommand.ExecuteReader())
                    {
                        var feedCount = 0;
                        while (dataReader.Read())
                        {
                            var feedItemId = dataReader.GetGuid(0);
                            feedNomberById.Add(feedItemId, feedCount);
                            feedIdByNomber.Add(feedCount, feedItemId);
                            feedCount++;
                        }

                        dataReader.NextResult();

                        var wordCount = 0;
                        while (dataReader.Read())
                        {
                            var wordId = dataReader.GetInt32(0);
                            wordNomberById.Add(wordId, wordCount);
                            wordIdByNomber.Add(wordCount, wordId);
                            wordCount++;
                        }
                        dataReader.NextResult();
                        source = new double[feedCount, wordCount];
                        while (dataReader.Read())
                        {
                            var feedItemId = dataReader.GetGuid(0);
                            var wordId = dataReader.GetInt32(1);
                            int count = dataReader.GetInt32(2);
                            source[feedNomberById[feedItemId], wordNomberById[wordId]] = count;
                        }
                    }
                }
                var result = Lsa.Compute(source, 0.025);
                var resultTable = new SqlDataRecord(
                    new SqlMetaData("DataSetId", SqlDbType.Int),
                    new SqlMetaData("FeedItemId", SqlDbType.UniqueIdentifier),
                    new SqlMetaData("WordId", SqlDbType.Int),
                    new SqlMetaData("Weight", SqlDbType.Float)
                    );
                SqlContext.Pipe.SendResultsStart(resultTable);
                for (int i = 0; i < result.GetLength(0); i++)
                {
                    for (int j = 0; j < result.GetLength(1); j++)
                    {
                        resultTable.SetValues(dataSetId, feedIdByNomber[i], wordIdByNomber[j], result[i, j]);
                    }
                }
                SqlContext.Pipe.SendResultsEnd();
            }
        }
    };
}
